#include <iostream>
#include <unistd.h>
#include <vector>

#include "Thread.hpp"

using std::vector;

int ticket = 1000;                                 // 多线程可以直接访问
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 初始化全局锁,也可以是局部的

//局部锁用 pthread_mutex_init()

// void GetTicket(string name)
// {
//     while (1)
//     {
//         pthread_mutex_lock(&mutex); // 加锁
//         // 在同一时刻，只允许一个线程申请锁成功! 多个线程申请锁失败，失败的线程在mutex上阻塞等待
//         if (ticket > 0)
//         {                 // 在加锁的时候,线程可能被切换,但是线程在切换时带走了[钥匙]，别的进程也无法进行修改
//             usleep(1000); // 1000微秒
//             cout << name << " get a ticket: " << ticket-- << endl;
//             pthread_mutex_unlock(&mutex); // 解锁
//         }
//         else
//         {
//             pthread_mutex_unlock(&mutex); // 解锁
//             break;
//         }
//     }

//     // 模拟抢票，实际情况还有很多后续代码
// }

void GetTicket(pthread_mutex_t* mutex)
{
    while (1)
    {
        pthread_mutex_lock(mutex); // 加锁
        // 在同一时刻，只允许一个线程申请锁成功! 多个线程申请锁失败，失败的线程在mutex上阻塞等待
        if (ticket > 0)
        {                 // 在加锁的时候,线程可能被切换,但是线程在切换时带走了[钥匙]，别的进程也无法进行修改
            usleep(1000); // 1000微秒
            cout << " get a ticket: " << ticket-- << endl;
            pthread_mutex_unlock(mutex); // 解锁
        }
        else
        {
            pthread_mutex_unlock(mutex); // 解锁
            break;
        }
    }

    // 模拟抢票，实际情况还有很多后续代码
}

// 应用方的文件
string GetThreadName()
{
    static int number = 1;
    char name[64];
    snprintf(name, sizeof name, "Thread-%d", number++);
    return name;
}

void Print(int NUM)
{
    while (NUM--)
    {
        cout << "hello world" << endl;
        sleep(1);
    }
}

int main()
{
    pthread_mutex_t mutex;             //创建局部锁
    pthread_mutex_init(&mutex,nullptr); //初始化局部锁

    string name1 = GetThreadName();
    Thread<pthread_mutex_t*> t1(GetTicket, name1, &mutex);

    string name2 = GetThreadName();
    Thread<pthread_mutex_t*> t2(GetTicket, name2, &mutex);

    string name3 = GetThreadName();
    Thread<pthread_mutex_t*> t3(GetTicket, name3, &mutex);

    string name4 = GetThreadName();
    Thread<pthread_mutex_t*> t4(GetTicket, name4, &mutex);

    t1.Start();
    t2.Start();
    t3.Start();
    t4.Start();

    t1.Join();
    t2.Join();
    t3.Join();
    t4.Join();

    pthread_mutex_destroy(&mutex);

    // string name1 = GetThreadName();
    // Thread<string> t1(GetTicket,name1,name1);

    //  string name2 = GetThreadName();
    // Thread<string> t2(GetTicket,name2,name2);

    //  string name3 = GetThreadName();
    // Thread<string> t3(GetTicket,name3,name3);

    //  string name4 = GetThreadName();
    // Thread<string> t4(GetTicket,name4,name4);

    // t1.Start();
    // t2.Start();
    // t3.Start();
    // t4.Start();

    // t1.Join();
    // t2.Join();
    // t3.Join();
    // t4.Join();

    // const int NUM = 5;
    // vector<Thread<int> *> threads;

    // for (int i = 0; i < NUM; i++)
    // {
    //     threads.push_back((new Thread<int>(Print, GetThreadName(),10)));
    // }

    // for (auto e : threads)
    // {
    //     cout << e->ThreadName() << ", is running" << e->IsRunning() << endl;
    // }

    // for (auto e : threads)
    // {
    //     e->Start();
    // }

    // sleep(1);
    // for (auto e : threads)
    // {
    //     cout << e->ThreadName() << ", is running" << e->IsRunning() << endl;
    // }

    // for (auto e : threads)
    // {
    //     int n = e->Join();
    //     cout<<"pthread wait succeed! "<<endl;
    // }

    // Thread t(Print,GetThreadName());
    // cout<<"create new Thread . Is running? "<<t.IsRunning()<<endl;

    // t.Start();

    // t.Join();
}